package com.xtpt.disaster.common.SQLServer;

import com.xtpt.disaster.bean.DbnodeInfo;
import com.xtpt.disaster.common.ClientCmdBuilder;
import com.xtpt.disaster.common.PropertyConfig;
import com.xtpt.disaster.common.consts.DBEnum;
import com.xtpt.disaster.common.consts.DataTypeEnum;
import com.xtpt.disaster.common.consts.OSTypeEenum;
import com.xtpt.disaster.utils.ServerPathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jack_xin
 * @ClassName SQLServerCmdBuilder
 * @Desc TODO
 * @date 2021年12月08日 9:37
 * @Version TODO
 */
@Component
public class SQLServerCmdBuilder extends ClientCmdBuilder {
    @Autowired
    PropertyConfig config;
    @Autowired
    ServerPathUtil pathUtil;

    /**
     * 客户端操作系统类型
     */
    private OSTypeEenum osType;
    /**
     * 启动或停止达梦服务命令格式(默认Linux)
     */
    private String serviceCmdFormat="service %2$s %1$s";;
    /**
     * 客户端节点信息
     */
    private DbnodeInfo clientDBNodeInfo;
    /**
     * 构造函数
     * @throws Exception 异常
     */
    public SQLServerCmdBuilder(){
        super();
    }

    /**
     * 设置客户端节点信息
     * @param nodeInfo 客户端节点
     * @return this
     * @throws Exception
     */
    public SQLServerCmdBuilder initializeWithClientNode(DbnodeInfo nodeInfo) throws Exception {
        //设置客户端则初始化父类
        super.init();
        this.clientDBNodeInfo=nodeInfo;
        super.setOSType(OSTypeEenum.getObject(nodeInfo.getNodeOsType()));
        return this;
    }

    public SQLServerCmdBuilder TransactionFilesToClient(String clientFilePath,
                                                        String serverFilePath,
                                                        String serverPort)
    {
        if(serverPort==null)
        {
            serverPort="22";
        }
        String useTool="scp -o StrictHostKeyChecking=no";
        if(config.isScpNeedPass())
        {
            if(osType==OSTypeEenum.LINUX) {
                useTool = String.format("sshpass -p %s %s", config.getServerPassword(),useTool);
            }
            else
            {
                useTool = String.format("pscp -pw %s", config.getServerPassword());
            }
        }
        String trans="%s -P %s %s@%s:%s \"%s\"";
        String transCmd = String.format(trans,
                useTool,
                serverPort,
                config.getServerAccount(),
                config.getServerIp(),
                serverFilePath,
                clientFilePath
                );
        AddCmdWithNewGroupLn(transCmd);
        return this;
    }

    /**
     * 将客户端文件传递回到服务端
     * @return this
     */
    public SQLServerCmdBuilder TransactionFilesToServer(String clientFilePath,
                                                 String serverFilePath,
                                                 String serverPort)
    {
        if(serverPort==null)
        {
            serverPort="22";
        }
        String useTool="scp -o StrictHostKeyChecking=no -r";
        String trans="%s -P %s ";
        if(config.isScpNeedPass())
        {
            if(osType==OSTypeEenum.LINUX) {
                useTool = String.format("sshpass -p %s %s", config.getServerPassword(),useTool);
                trans += "%s  %s@%s:%s";
            }
            else
            {
                useTool = String.format("pscp -pw %s -r", config.getServerPassword());
                trans += "\"%s\"  %s@%s:%s";
            }
        }
        String transCmd = String.format(trans,
                useTool,
                serverPort,
                clientFilePath,
                config.getServerAccount(),
                config.getServerIp(),
                serverFilePath);
        AddCmdWithNewGroupLn(transCmd);
        return this;
    }

    /*
     * @Author jack xin
     * @Method Name dbSQLServerBackUp
     * @Desc 执行生成的备份命令，放入一个命令组中执行，返回Map<备份文件所在的本地路径, 服务器存储的路径>
     * @Param [taskId, backFileName, FullOrIncrement, disc, backFlag]
     * @return java.util.Map<java.lang.String,java.lang.String>
     * @Date 11:20 2021/12/8
    **/
    public Map<String,String> dbSQLServerBackUp(String taskId, String backFileName, String FullOrIncrement, String disc, String backFlag) throws Exception {
        Map<String,String> pathMap = new HashMap<>();
        //生成本地备份文件的全文件名
        String fullFileName = backFileName + config.getBackFileExtend();
        //生成服务器路径
        String serverFilePathRoot = pathUtil.getServerPath(taskId,
                null,
                DataTypeEnum.DATABASE.getValue(),
                DBEnum.SQLSERVER.getValue(),
                FullOrIncrement);

        String clientFilePath = clientDBNodeInfo.getNodeDbBackupPath() + "\\" +fullFileName;
        String serverFilePath = serverFilePathRoot + "/" + fullFileName;

        String command = SQLServerCommandGenerator.BackupCommand(this.clientDBNodeInfo, clientFilePath);

        // 实际数据库备份流程，通过conn语句在客户端上连接数据库，然后执行备份指令sql，备份完成后退出，最后使用scp或者pscp命令传输备份文件到服务器上。
        AddCmdWithNewGroupLn(command).AddCmdLn("exit").TransactionFilesToServer(clientFilePath,
                serverFilePath,
                config.getServerSshPort());
        pathMap.put(serverFilePath, clientFilePath);
        return pathMap;
    }

    /*
     * @Author jack xin
     * @Method Name dbSQLServerRecover
     * @Desc 执行生成的备份命令，放入一个命令组中执行，返回Map<备份文件所在的本地路径, 服务器存储的路径>
     * @Param [taskId, backFileName, FullOrIncrement, disc, backFlag]
     * @return java.util.Map<java.lang.String,java.lang.String>
     * @Date 11:20 2021/12/8
     **/
    public Map<String, String> dbSQLServerRecover(String clientPath, String serverPath, List<String> command) {
        Map<String,String> pathMap = new HashMap<>();
        TransactionFileToClient(serverPath, clientPath);
        AddCmdWithNewGroupLn(command.get(1)).AddCmdLn("exit");
        pathMap.put(clientPath, serverPath);
        return pathMap;
    }

    @Override
    public Map<String, String> dbBackUp(String taskId, String backFileName, String FullOrIncrement, String disc, String backFlag) throws Exception {
        return null;
    }

    @Override
    public ClientCmdBuilder dbRestore(String mainRestoreFilePathOnClient, List<String> allBackupFiles) {
        return null;
    }

    //////////////////////////////////////////////////// 如下重写父类方法
    /**
     * 新添加命令组并将命令加入到新组（自动加回车符）
     * @param cmd 命令字符串
     * @return this
     */
    public SQLServerCmdBuilder AddCmdLn(String cmd)
    {
        super.AddCmdLn(cmd);
        return this;
    }

    /**
     * 新添加命令组并将命令加入到新组（自动加回车符）
     * @param cmd 命令字符串
     * @return this
     */
    public SQLServerCmdBuilder AddCmd(String cmd)
    {
        super.AddCmd(cmd);
        return this;
    }
    /**
     * 新添加命令组并将命令加入到新组（自动加回车符）
     * @param cmd 命令字符串
     * @return this
     */
    public SQLServerCmdBuilder AddCmdWithNewGroupLn(String cmd)
    {
        super.AddCmdWithNewGroupLn(cmd);
        return this;
    }

    /**
     * 新添加命令组并将命令加入到新组（自动加回车符）
     * @param cmd 命令字符串
     * @return this
     */
    public SQLServerCmdBuilder AddCmdWithNewGroup(String cmd)
    {
        super.AddCmdWithNewGroup(cmd);
        return this;
    }

}
